/* This file is part of the Palabos library.
 *
 * Copyright (C) 2011-2015 FlowKit Sarl
 * Route d'Oron 2
 * 1010 Lausanne, Switzerland
 * E-mail contact: contact@flowkit.com
 *
 * The most recent release of Palabos can be downloaded at 
 * <http://www.palabos.org/>
 *
 * The library Palabos is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * The library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/** \file
 * Descriptor for nearest-neighbor 3D lattices -- generic code.
 **/
#ifndef EXTENDED_NEIGHBORHOOD_LATTICES_3D_HH
#define EXTENDED_NEIGHBORHOOD_LATTICES_3D_HH

#include "latticeBoltzmann/nearestNeighborLattices3D.h"

namespace plb {

namespace descriptors {
    
    // D3Q121 ////////////////////////////////////////////////////////////
    
    template<typename T>
    const T D3Q121Constants<T>::invD = (T)1 / (T) d;
    
    template<typename T>
    const int D3Q121Constants<T>::vicinity = 3;
    
    template<typename T>
    const int D3Q121Constants<T>::c[D3Q121Constants<T>::q][D3Q121Constants<T>::d] =
    {
        {0, 0, 0}, 
        {-3, -3, -3}, {-3, -3, 3}, {-3, -2, 0}, {-3, -1, -1}, {-3, -1, 1}, 
        {-3, 0, -2}, {-3, 0, 0}, {-3, 0, 2}, {-3, 1, -1}, {-3, 1, 1}, 
        {-3, 2, 0}, {-3, 3, -3}, {-3, 3, 3}, {-2, -3, 0}, {-2, -2, -2}, 
        {-2, -2, 0}, {-2, -2, 2}, {-2, -1, 0}, {-2, 0, -3}, {-2, 0, -2}, 
        {-2, 0, -1}, {-2, 0, 1}, {-2, 0, 2}, {-2, 0, 3}, {-2, 1, 0}, 
        {-2, 2, -2}, {-2, 2, 0}, {-2, 2, 2}, {-2, 3, 0}, {-1, -3, -1}, 
        {-1, -3, 1}, {-1, -2, 0}, {-1, -1, -3}, {-1, -1, -1}, {-1, -1, 1}, 
        {-1, -1, 3}, {-1, 0, -2}, {-1, 0, 0}, {-1, 0, 2}, {-1, 1, -3}, 
        {-1, 1, -1}, {-1, 1, 1}, {-1, 1, 3}, {-1, 2, 0}, {-1, 3, -1}, 
        {-1, 3, 1}, {0, -3, -2}, {0, -3, 0}, {0, -3, 2}, {0, -2, -3}, 
        {0, -2, -2}, {0, -2, -1}, {0, -2, 1}, {0, -2, 2}, {0, -2, 3}, 
        {0, -1, -2}, {0, -1, 0}, {0, -1, 2}, {0, 0, -3}, {0, 0, -1}, 
        {3, 3, 3}, {3, 3, -3}, {3, 2, 0}, {3, 1, 1}, {3, 1, -1}, 
        {3, 0, 2}, {3, 0, 0}, {3, 0, -2}, {3, -1, 1}, {3, -1, -1}, 
        {3, -2, 0}, {3, -3, 3}, {3, -3, -3}, {2, 3, 0}, {2, 2, 2}, 
        {2, 2, 0}, {2, 2, -2}, {2, 1, 0}, {2, 0, 3}, {2, 0, 2}, 
        {2, 0, 1}, {2, 0, -1}, {2, 0, -2}, {2, 0, -3}, {2, -1, 0}, 
        {2, -2, 2}, {2, -2, 0}, {2, -2, -2}, {2, -3, 0}, {1, 3, 1}, 
        {1, 3, -1}, {1, 2, 0}, {1, 1, 3}, {1, 1, 1}, {1, 1, -1}, 
        {1, 1, -3}, {1, 0, 2}, {1, 0, 0}, {1, 0, -2}, {1, -1, 3}, 
        {1, -1, 1}, {1, -1, -1}, {1, -1, -3}, {1, -2, 0}, {1, -3, 1}, 
        {1, -3, -1}, {0, 3, 2}, {0, 3, 0}, {0, 3, -2}, {0, 2, 3}, 
        {0, 2, 2}, {0, 2, 1}, {0, 2, -1}, {0, 2, -2}, {0, 2, -3}, 
        {0, 1, 2}, {0, 1, 0}, {0, 1, -2}, {0, 0, 3}, {0, 0, 1}, 
    };


    
    template<typename T>
    const int D3Q121Constants<T>::cNormSqr[D3Q121Constants<T>::q] =
    {
        0, 
        27, 27, 13, 11, 11, 13, 9, 13, 11, 11, 13, 
        27, 27, 13, 12, 8, 12, 5, 13, 8, 5, 5, 8, 
        13, 5, 12, 8, 12, 13, 11, 11, 5, 11, 3, 3, 
        11, 5, 1, 5, 11, 3, 3, 11, 5, 11, 11, 
        13, 9, 13, 13, 8, 5, 5, 8, 13, 5, 1, 
        5, 9, 1, 27, 27, 13, 11, 11, 13, 9, 13, 
        11, 11, 13, 27, 27, 13, 12, 8, 12, 5, 
        13, 8, 5, 5, 8, 13, 5, 12, 8, 12, 13, 
        11, 11, 5, 11, 3, 3, 11, 5, 1, 5, 11, 
        3, 3, 11, 5, 11, 11, 13, 9, 13, 13, 
        8, 5, 5, 8, 13, 5, 1, 5, 9, 1, 
    };
    
    template<typename T>
    const T D3Q121Constants<T>::t[D3Q121Constants<T>::q] =
    {
        3.059162202948600642469372949253824201326e-02, 
        6.928750896386028525506511533901772605647e-07, 
        6.928750896386028525506511533901772605647e-07, 
        1.431862411548029405509826922297073180664e-05, 
        1.068340024593910949171102482709870577810e-04, 
        1.068340024593910949171102482709870577810e-04, 
        1.431862411548029405509826922297073180664e-05, 
        3.247475270880738129679305570682130634477e-04, 
        1.431862411548029405509826922297073180664e-05, 
        1.068340024593910949171102482709870577810e-04, 
        1.068340024593910949171102482709870577810e-04, 
        1.431862411548029405509826922297073180664e-05, 
        6.928750896386028525506511533901772605647e-07, 
        6.928750896386028525506511533901772605647e-07, 
        1.431862411548029405509826922297073180664e-05, 
        1.810217515763742375901616857556491604089e-04, 
        4.281835936810840661857590214080748494426e-04, 
        1.810217515763742375901616857556491604089e-04, 
        6.111023366833424322414921694060723126594e-03, 
        1.431862411548029405509826922297073180664e-05, 
        4.281835936810840661857590214080748494426e-04, 
        6.111023366833424322414921694060723126594e-03, 
        6.111023366833424322414921694060723126594e-03, 
        4.281835936810840661857590214080748494426e-04, 
        1.431862411548029405509826922297073180664e-05, 
        6.111023366833424322414921694060723126594e-03, 
        1.810217515763742375901616857556491604089e-04, 
        4.281835936810840661857590214080748494426e-04, 
        1.810217515763742375901616857556491604089e-04, 
        1.431862411548029405509826922297073180664e-05, 
        1.068340024593910949171102482709870577810e-04, 
        1.068340024593910949171102482709870577810e-04, 
        6.111023366833424322414921694060723126594e-03, 
        1.068340024593910949171102482709870577810e-04, 
        2.752500532563812386479902897409233864522e-02, 
        2.752500532563812386479902897409233864522e-02, 
        1.068340024593910949171102482709870577810e-04, 
        6.111023366833424322414921694060723126594e-03, 
        9.851595103726339186467408722380536926020e-02, 
        6.111023366833424322414921694060723126594e-03, 
        1.068340024593910949171102482709870577810e-04, 
        2.752500532563812386479902897409233864522e-02, 
        2.752500532563812386479902897409233864522e-02, 
        1.068340024593910949171102482709870577810e-04, 
        6.111023366833424322414921694060723126594e-03, 
        1.068340024593910949171102482709870577810e-04, 
        1.068340024593910949171102482709870577810e-04, 
        1.431862411548029405509826922297073180664e-05, 
        3.247475270880738129679305570682130634477e-04, 
        1.431862411548029405509826922297073180664e-05, 
        1.431862411548029405509826922297073180664e-05, 
        4.281835936810840661857590214080748494426e-04, 
        6.111023366833424322414921694060723126594e-03, 
        6.111023366833424322414921694060723126594e-03, 
        4.281835936810840661857590214080748494426e-04, 
        1.431862411548029405509826922297073180664e-05, 
        6.111023366833424322414921694060723126594e-03, 
        9.851595103726339186467408722380536926020e-02, 
        6.111023366833424322414921694060723126594e-03, 
        3.247475270880738129679305570682130634477e-04, 
        9.851595103726339186467408722380536926020e-02, 
        6.928750896386028525506511533901772605647e-07, 
        6.928750896386028525506511533901772605647e-07, 
        1.431862411548029405509826922297073180664e-05, 
        1.068340024593910949171102482709870577810e-04, 
        1.068340024593910949171102482709870577810e-04, 
        1.431862411548029405509826922297073180664e-05, 
        3.247475270880738129679305570682130634477e-04, 
        1.431862411548029405509826922297073180664e-05, 
        1.068340024593910949171102482709870577810e-04, 
        1.068340024593910949171102482709870577810e-04, 
        1.431862411548029405509826922297073180664e-05, 
        6.928750896386028525506511533901772605647e-07, 
        6.928750896386028525506511533901772605647e-07, 
        1.431862411548029405509826922297073180664e-05, 
        1.810217515763742375901616857556491604089e-04, 
        4.281835936810840661857590214080748494426e-04, 
        1.810217515763742375901616857556491604089e-04, 
        6.111023366833424322414921694060723126594e-03, 
        1.431862411548029405509826922297073180664e-05, 
        4.281835936810840661857590214080748494426e-04, 
        6.111023366833424322414921694060723126594e-03, 
        6.111023366833424322414921694060723126594e-03, 
        4.281835936810840661857590214080748494426e-04, 
        1.431862411548029405509826922297073180664e-05, 
        6.111023366833424322414921694060723126594e-03, 
        1.810217515763742375901616857556491604089e-04, 
        4.281835936810840661857590214080748494426e-04, 
        1.810217515763742375901616857556491604089e-04, 
        1.431862411548029405509826922297073180664e-05, 
        1.068340024593910949171102482709870577810e-04, 
        1.068340024593910949171102482709870577810e-04, 
        6.111023366833424322414921694060723126594e-03, 
        1.068340024593910949171102482709870577810e-04, 
        2.752500532563812386479902897409233864522e-02, 
        2.752500532563812386479902897409233864522e-02, 
        1.068340024593910949171102482709870577810e-04, 
        6.111023366833424322414921694060723126594e-03, 
        9.851595103726339186467408722380536926020e-02, 
        6.111023366833424322414921694060723126594e-03, 
        1.068340024593910949171102482709870577810e-04, 
        2.752500532563812386479902897409233864522e-02, 
        2.752500532563812386479902897409233864522e-02, 
        1.068340024593910949171102482709870577810e-04, 
        6.111023366833424322414921694060723126594e-03, 
        1.068340024593910949171102482709870577810e-04, 
        1.068340024593910949171102482709870577810e-04, 
        1.431862411548029405509826922297073180664e-05, 
        3.247475270880738129679305570682130634477e-04, 
        1.431862411548029405509826922297073180664e-05, 
        1.431862411548029405509826922297073180664e-05, 
        4.281835936810840661857590214080748494426e-04, 
        6.111023366833424322414921694060723126594e-03, 
        6.111023366833424322414921694060723126594e-03, 
        4.281835936810840661857590214080748494426e-04, 
        1.431862411548029405509826922297073180664e-05, 
        6.111023366833424322414921694060723126594e-03, 
        9.851595103726339186467408722380536926020e-02, 
        6.111023366833424322414921694060723126594e-03, 
        3.247475270880738129679305570682130634477e-04, 
        9.851595103726339186467408722380536926020e-02 
    };

    
    template<typename T>
    const T D3Q121Constants<T>::cs2 = 1./ ( 1.19697977039307435897238846385* 1.19697977039307435897238846385);
    
    template<typename T>
    const T D3Q121Constants<T>::invCs2 =  1.19697977039307435897238846385* 1.19697977039307435897238846385;
    
    template<typename T>
    const char D3Q121Descriptor<T>::name[] = "D3Q121";
    
    template<typename T>
    const char ForcedD3Q121Descriptor<T>::name[] = "ForcedD3Q121";

}  // namespace descriptors

}  // namespace plb

#endif
